package md.specialEqp;


import graphql.relay.Connection;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.GraphQLObjectType;
import lombok.*;
import lombok.experimental.SuperBuilder;
import md.cm.geography.Adminunit;
import md.cm.geography.Village;
import md.cm.unit.Division;
import md.cm.unit.Unit;
import md.specialEqp.inspect.Isp;
import org.fjsei.yewu.aop.hibernate.AdminunitBinder;
import org.fjsei.yewu.aop.hibernate.NodeIdBinder;
import org.fjsei.yewu.aop.hibernate.NodeIdNameBinder;
import org.fjsei.yewu.aop.hibernate.UnitNameBinder;
import org.fjsei.yewu.filter.Node;
import org.fjsei.yewu.filter.Uunode;
import org.fjsei.yewu.graphql.MemoryListConnection;
import org.fjsei.yewu.index.AdminunitEs;
import org.fjsei.yewu.index.EqpEs;
import org.fjsei.yewu.index.UnitEs;
import org.fjsei.yewu.pojo.SliceSyncRes;
import org.fjsei.yewu.util.Tool;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.search.engine.backend.types.Aggregable;
import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.PropertyBinderRef;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.util.Assert;

import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import static jakarta.persistence.FetchType.EAGER;
import static jakarta.persistence.FetchType.LAZY;

//import org.springframework.data.annotation.Transient;
//import org.springframework.data.elasticsearch.annotations.Field;

//同名冲突！@Cache不是来自jakarta.persistence.*的，所以添加org.hibernate.annotations.Cache在其上方。或直接@org.hibernate.annotations.Cache上了。

//云数据库网关服务 支持跨DB实例SQL关联查询; 但是无法确保事务，数据一致性毛病？

//懒加载导致了N+1问题(按照后面逻辑代码需求再去那可能的会执行N条SQL)，假设不用懒加载的EAGER话就会强行加载可能根本就不会用到的大量的关联数据(不是更浪费?)。
//EntityGraph是和LAZY相反的？，总体写死掉策略搞lazy，动态的个性化查询用EntityGraph来提示{深度定制的,细化,仅针对个别使用到的字段的}，俩个机制的目标完全冲突。
//Lazy字段才需要搞@NamedEntityGraph的，嵌套Lazy字段/下一级Lazy属性字段用@NamedSubgraph。目的提前join取数据,减少sql语句数,能提高效率。不是FetchType.LAZY的就没必要@EntityGraph。
//举例@NamedEntityGraph(name="Eqp.task",attributeNodes={@NamedAttributeNode("task"),@NamedAttributeNode("isps")}) 关联不密切的关联对象一次性join=会产生爆炸记录数；
//EntityGraph不可随便加;就为了多出一个isps关联对象left outer join ？,对多出join约束性少引起笛卡儿积级别记录个数爆炸，本来只有290条变成12588条了。
//EntityGraph存在理由:提示JPA去屏蔽LAZY，用JOIN FETCH一次关联表全查，减少SQL语句(规避了1+N 问题)，从而提高速度；但也失去懒加载优点。https://blog.csdn.net/dm_vincent/article/details/53366934
//对于@NamedEntityGraphs({ @NamedEntityGraph每条定义尽量精简，不要太多字段，必须每一条/每一个接口都要测试对比/打印调试hibernate SQL。
//字段名称用了保留字导致表EQP无法自动建立！ 需手动创建最简单eqp表。 字段类型要用java包装类
//继承实体类做法：String=eqp.getDTYPE没有啊，无法在SQL获得派生类类型做过滤条件，不能在数据库直接过滤派生类类型。ElevatorRepository可只搜索本派生类，不灵活啊。
//@Entity可支持多个物理表合并的 @SecondaryTables({@SecondaryTable(name="EMP_DETAIL"),@SecondaryTable(name="EMP_HIST") })。

/**特种设备检验有8大类。JC_EQP_MGE；TB_EQP_MGE；
监察特有功能:许可证(单位/人员{监察/检验检测/无损检测/评审/协管/质保体系人员}/设备)；工作成效统计(作业人/监察人/考试机构{班级}/检验检测机构/检验人员/生产单位,整改率)，到期预警，
 证书到期预警；重要问题闭环，现场检查安排(指令书)；告知受理；检验相关审核(单位{安装改造维修/制造/设计/充装/检验机构/乡镇机构}变更/关键字段{使用单位}/设备状态变更/维保认领)。
 机构(评审/考试/培训)变更审核，作业人员聘用单位变更；设备<省外注册/迁出/流动设备/使用登记/首检录入/办证后管道新增确认>；许可{申请书}办证流程；考试审核，案件，诚信，维保准入。
不属于8大类的比如R000常压容器; 直接就是Eqp基类/没有独立参数表。
结构化字段非json的必要性：计费不会用，过滤不会用，常规统计不会用，后端服务器业务逻辑不会用，不是监察严格管制修改要审核的字段，满足这些的可以放json中。
 旧平台3个设备库：JC_TEMP_EQPMGE未注册临时库,正式JC_EQP_MGE,检验本地设备库{+制造库}。
重大毛病：JC_TEMP_EQPMGE实际是申请审批表！“设备的使用登记申请/施工申报/注册前置材料填写，首检录入的”，表面上JC_TEMP_EQPMGE临时设备过渡保存，可能是检验平台推送过来的。
 首检录入是检验平台先有设备和技术参数的，然后推送给监察临时表，监察审查注册若不通过的就无法进入正式表，临时表和参数表会遗留这些非监察关注设备(目录外的)。
 下一代平台？推送没必要了，直接告诉监察机构我在本平台的设备代码+检验机构可直接定位到Eqp,然后配合附加的申请录入的字段数据给监察平台的新设备注册申报接口？(不一定要复制先有数据)。
 JPA继承策略针对CRDB数据库Eqp实践：SINGLE_TABLE 39s,优于JOINED 51.1s,优于TABLE_PER_CLASS 55s最差的;
 注意@Indexed针对子类自动拆分独立的索引。若@Indexed(enabled=false)加在子类上导致不能针对该子类对应实体做索引,没办法把子类合并到基类索引上只能各自独立。
 报错没法上implements Uunode
 设备台账Eqp数据若设备被淘汰了，可继续保留期限5年后才物理删除。
 dtype字段：是JPA基类自己增加;
 */


@SuperBuilder(toBuilder=true)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
//@Table(indexes={@Index(columnList = "cod"), @Index(columnList = "oid") } ) 改成软约束程序负责控制唯一性
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Medium")
@Indexed(index="eqp")
public class Eqp implements Equipment, SliceSyncRes {
    //批量插入加速可用GenerationType.IDENTITY需要手工设置auto_increment;删除外键子表？用uuid最快但uuiid长多占存储。
    //Java默认的uuid工具便是Version 4 随机UUID这种UUID产生重复的概率是可以计算出来的。 https://blog.csdn.net/AwayFuture/article/details/103623751
    //CRDB的分布式id验证？
    //关联PipingUnit索引报错Unknown field 'pipe.id' Context: indexes [PipingUnit] 要求必须添加显式id索引字段，搜索注解交叉无法分辨真实目的。
    //需要保证非结构化json关联本对象的所有应用在尽快短暂的时间之内完成有效的利用，同时确保非结构化json关联在追溯利用最后时间之前本对象都不会被真正的删除掉，若可以保证的？
    //@KeywordField(sortable=Sortable.YES) 因为PipingUnit Isp关联需要
    //@GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID id;
    //用JPA中@Version来做web浏览后再更新的非数据库事务的面对业务层面并发读写控制。
    //乐观锁同步用，［注意］外部系统修改本实体数据就要改它version后一起commit事务。@Version防第二类更新丢失；外部更新version，我这读取依然受缓存影响。
    @Version
    private int  version;   //之前Timestamp类型ES过不了; 旧表H2还用timestamp

    /**EQP_USE_STA 状态码; 合并标记
     * 不能用保留字。private char  use ?　：若用了保留字导致表EQP无法自动建立！
     * 该条设备记录已被设置成了删除态不再有效，就等待以后维护程序去清理这些被历史淘汰的数据了。
     *     @NotNull
     * 合并删除标记   private Boolean valid=true;
    */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    @Enumerated
    private UseState_Enum   ust;
    /** 使用状态 状态变更日期：USESTA_CHG_DATE;
     * */
    private LocalDate  uscd;
    /**EQP_REG_STA 注册状态 注册登记状态
     * 不能用private char   在H2无法建，Character占2字节
     */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    @Enumerated
    private RegState_Enum   reg;
    //@PropertyDef(label="监察识别码")    数据库建表注释文字。
    //@Column(length =128, unique = true)

    /**OIDNO每一个省份监察机构自己产生的易识别码。最多40 char
     * 不同监察省份的 可能有相同代码。
     * 移除监察后的清空OIDNO=null ?;
     * JC_NOTIFI_EQPASS临注册前设备见到OIDNO了！ 给==>告知单。
     * */
    @FullTextField(analyzer = "ngram_analyzer")
    @KeywordField(name ="oid_sort", sortable=Sortable.YES)
    @Column(length =40)
    private String oid;

    /**检验机构自己编纂的代码，旧平台设备代码
     * EQP_COD 旧平台的设备号? 本平台自己产生的或照抄老旧平台产生的。
     * 对接旧平台用的，新平台没有意义。 直接用OIDNO；旧平台EQP_COD没存在必要;
     * @Size(min = 4, max = 32)  ? 允许为空; 但是确保（cod + ispu.id）两个组合唯一性。
     * */
    @FullTextField(analyzer = "ngram_analyzer")         //至少3个连续符号的分词搜索
    @KeywordField(name ="cod_sort", sortable=Sortable.YES)
    private String cod;

    //光用继承实体类不好解决问题，还是要附加冗余的类别属性；特种设备分类代码 层次码4个字符/大写字母 ；可仅用前1位、前2位或前3位代码；
    /**设备种类 EQP_TYPE{首1个字符} ,   Eqp.type不能修改的。
     * 用实体类java类型区别，只是在服务器内存中区分操作的, if(eQP instanceof Elevator)
     *  ((Elevator) eQP).setxxx;，难道要把数据集全部搜到内存中来; 要直接要在数据库DB来设置SQL层次过滤？
     * 继承派生缺点，Hibernate语句生成超长。就算派生继承，还得要再搞个字段表示继承类的类型方便SQL过滤。
     * 数据集中在：3电梯 2容器 4起重; 电梯再按区域SUBSTR(EQP_AREA_COD,1,4)划分前3个："3501","3502","3505"地市。
     * 对于Vessel子类可有两个type=‘2’||‘R’;
     * */
    @KeywordField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    @Column(nullable = false)
    @Size(min = 1, max = 1)
    private String type;

    /**设备类别代码 EQP_SORT{首2个字符} ,
     * 62个; 主要是前15类别。
     * 可为空
     * 例外排除:压力容器(2300气瓶1亿只)；两工地的是归属住建厅管的=不属于对口部门。
     * 注意旧平台同步数据差错：起重机械竟然有sort='31','4/','04','4B'等；
     * */
    @KeywordField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    @Size(min = 2, max = 2)
    private String sort;
    /**设备品种代码 EQP_VART{首3个字符}
     * 142个; 分布非常不均，前30品种。光光3110有246134条。
     * 可为空
     * */
    @KeywordField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    @Size(min = 3, max = 3)
    private String vart;

    /**SUB_EQP_VART 子设备品种？{非国家标准的扩展分类} 用于做报告 选择模板/ 收费计算参数【最详细分类代码】。
     * 22个, 计费 在后端服务器中 可能用的。在JC_TEMP_EQPMGE没有SUB_EQP_VART字段[监察不关心，检验机构自己添加字段(业界统一)]
     * 可为空， 旧平台9999=无
     * [非树状分解的]可能对于不同 vart 却有重复的subv代码。?
     * */
    @KeywordField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private String subv;

    /**目录属性 目录外 IN_CAG  1:目录内，2：目录外 目录外的{针对设备}不一定不能是法定的{针对业务操作}性质
     * 责任范畴？ =（私宅电梯）转公用判断 IF_JCINCAG ；"IF_JCINCAG""转公用1是默认为空"==极度少见才9条都是电梯监察可能查不到的。
     * 监察平台没有IN_CAG和IF_JCINCAG字段；
     * 前端 没有录入编辑？ 该字段的实际在 目录变更申请=特殊的菜单命令；
     * 首检录入{OIDNO: "QA29292", EQP_COD: "3501T57843"}，监察正式表没有，临时申请表有数据，检验有=目录外的。
     * */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private Boolean  ocat;
    /**EQP_STATION_COD 设备代码(设备国家代码)*/
    @KeywordField
    private String sno;

    /**EQP_USECERT_COD 使用证号 ,有重复数据/管道或/省略的。
     * 有可能更换号码，换证？新号
     * 受理=>许可审查=>生成使用证号和注册代码=>流转到审批环节=>设备写入正式库=〉制证。
     * */
    @KeywordField
    private String cert;
    /**发证日期：CERT_DATE;
     * */
    private LocalDate cerd;
    /**EQP_REG_COD 监察注册代码 设备注册号 eqp_reg_sta不同的就可重复
     * eqp_reg_cod=NEW_EQP_REG_COD 注册代码 和eqp_reg_sta相关;
     * 注册码还会有变动和新的; EQP_REG_COD注册代码/管道重复的；
     * 设备迁出oidno=null;迁出后资料EQP_REG_COD设备代码=保存时间年限多久20年 使用超过20年;
     * */
    @KeywordField
    private String rcod;

    /**设备等级 EQP_LEVEL {设计时标注的，每种设备Enum可不一样}  主表的"EQP_LEVEL"字段,
     * [合并字段]游乐 技术表.AMUS_TYPE游乐设施级别 ; 管道技术表.PIPELINE_LEVEL，管道独立的?总的级别，但底下所属单元可有自己级别。
     * 设计上的级别; 目前随意，每一个大类都有不同编码的？直接String但是隐形约束输入。
     * 关键的等级有些已直接体现到设备{容器第二类}类别上了。
     * 游乐设施的，同步AMUS_TYPE设备级别
     * 前端只针对 【4000起重 游乐 管道】 这3个种/类才有输入页面,其他种类无意义=不设置！。
     * 监察的 EQP_CLASS_COD 字段没存在的意义。
     * 检验的CLASS_COD"产品分类代码:1004微压炉",IF_WYL是否微压炉：TB_DICT_FEESTANDARD +TB_DICT_FEEFIELD也没找到计费项，所以实际废弃CLASS_COD;
     * 分配检验机构和检验部门的依据之一。
     *不必做搜索字段吗？ 人工|逻辑判定|批处理设置检验部门的，搜索是OLTP需求不等于批处理的离线流处理数据需求，流处理可用非CRDB其他数据库。
     */
    private String level;

    /**FACTORY_COD  出厂编号，+制造单位+型号=联合关键字了。
     * 若管道的 ，实际是工程描述、文本较长。管道装置的关键字应该看使用单位+出厂编号？?管道是整体工程而不是现成型设备/要设计要施工。
     * */
    @KeywordField
    private String fno;

    /**单位内部编号 EQP_INNER_COD, place No；搜索过滤用
     * 附加上后更加能精确定位某个地理空间的位置
     * */
    @FullTextField          //有必要注解为可搜索字段？
    private String plno;

    /**设备名称，EQP_NAME 设备(装置)名称：给使用单位看的 name ； 管道装置用到。
     * 管道工程或者固定式装置名称
     *【为了搜索定位】管道特别！ 旧平台直接用父类Eqp EQP_NAME字段,设备名称。初始化数据要倒腾转移。
     * 装置名称： BOX_NAME ;管道特别！把旧平台设备名称字段转给非搜索字段svp[管道设备名]=就是对调含义; PIPE_BOX_NAME,||=参数表的BOX_NAME;
     * 前端要特别提示：titl是管道装置名称，管道原本EQP统一字段含义的设备名称已经不重要了，管道EQP_NAME弱化保存到svp[管道设备名]字段，界面输入修改。
     额外的,旧监察+检验主表实际有"PIPE_BOX_NAME"字段可是JY上只有50条数据,JC只有15条:==形同作废字段。
     distict本字段有4.9万：“福清70万吨聚烯烃薄膜项目车间一锅炉及预留燃气工程”这类的都是设备品种位置等用户自己明白的自定义描述；
     感觉根本没必要依照本字段搜索，所以去掉 @FullTextField 注解。
     */
    private String  titl;

    /**EQP_MOD 设备型号, 有没有型号外部编码规范，可能随意填？监察关心!监察严格管制修改要审核的字段
     * 监察搜索过滤用, 监察严格修改管控字段；
     * */
    @KeywordField(aggregable=Aggregable.YES)
    private String  model;

    /**是否正在安装监检{检验业务状态/时间长、监察关心注册} IF_INCPING , 相关IF_NOREG_LEGAR非注册法定设备（未启用）
     * 改造大修 安装监检或改造监检 EQP_REG_STA=0？ 检验竟然设置注册状态？
     * 监检中了，定检就跳过吗（普通规则失效）,管道装置大；
     * 业务影响的 状态切换标记？ 很像业务状态锁。
     * */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private Boolean  cping;
    /**IF_MAJEQP 是否重要特种设备 只用于显示过滤，
     * "IF_MAJCTL""是否重点监控"=是监察的关注标记。
     * 监察初始化设置的关照级别。 IF_MAJEQP 11200台，IF_MAJCTL 1300，&&双重的630；
     旧检验 MAJEQP_TYPE ,"重点关注设备类型"，纯粹为了前端标记颜色if(field=="IF_MAJEQP"){if(MAJEQP_TYPE=="1"&&SDNAPPLYID!=null):red;}后端没用到MAJEQP_TYPE字段。
     MAJEQP_TYPE="A类" 2300条, ？作废？实际是监察平台的关注点做得标记。
     */
    private Boolean  vital;

     /**投入使用日期 FIRSTUSE_DATE 设备投用日期, 移装设备会修改？
     * 投用有磨损，应该比安装日期更关注。
     * 如果是监检，并且投用日期为空更新投用日期为检验日期
     * */
    private LocalDate used;

    /**制造日期：MAKE_DATE ，管道EQP_FINMAKE_DATE
     *  制造（安装）日期 ， 游乐设施需要判断下检日期和制造日期和设计使用年限
     * */
    private LocalDate mkd;
    /**安装竣工日期 INST_COMP_DATE (统计需要？,政策截止过滤 需要)，
     监察2表才有的字段 "INST_COMP_DATE","安装竣工日期 "；@ 旧检验平台没有这字段!
     @Temporal(TemporalType.DATE)
     private Date insd;  仅在jsp有INST_DATE=施工告知的日期。
     类似的字段还有：svp.竣验日(null!=jy? jy.getCompeAccpDate(): null )
     * */
    private LocalDate insd;

    /**使用年限到期时间,  DESIGN_USE_OVERYEAR 设计使用年限到期年份{精确到月}
     * 上结论：使用年限到期时间小于 投入使用时间+设计使用年限+延长使用年限;
     * 游乐定捡是否今年到期，如今年到期不受理定检 TO_CHAR(A.DESIGN_USE_OVERYEAR,'YYYY') <= TO_CHAR(SYSDATE,'YYYY')
     * 设计年限到期日期 从 DESIGN_USE_OVERYEAR_FROM至：DESIGN_USE_OVERYEAR_TO
     * 电梯绝大多数没有设置到期时间；电梯更新改造大修后敲定新一轮的到期时间? 电梯不看寿命只认定检结论的!
     * "EXTEND_USE_YEAR""延长使用年限";  "END_USE_DATE""使用年限到期时间(作废)";
     * */
    @GenericField(sortable=Sortable.YES)
    private LocalDate expire;

    /**是否流动设备 IS_MOVEEQP 可移动的/流动的在JC管理；
     * 流动作业设备才会出现省外JC注册　使用证/编码都是外省旧的,oidno才是新的。
     * */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private Boolean  move;
    //EQP_AREA_COD定义规律大乱；    //统计和行政含义的地址区分；
    //  private String  area;    //实际应该放入Address中, 暂用； EQP_AREA_COD 设备所在区域; 监察划区为牢
    //  private String addr;    //暂时用 EQP_USE_ADDR 使用地址 //该字段数据质量差！
    //.EQP_USE_PLACE场所性质　？不一样概念，或Address pos底下附加属性。
    //   private String occa;    //EQP_USE_OCCA 使用场合　.EQP_USE_OCCA起重才用
    //楼盘=地址的泛房型表达式;     单独设立一个模型对象。　(楼盘名称)＝使用地点！=使用单位的单位地址。
    //  private Long  buildId;    //暂用 BUILD_ID  楼盘ID

    /**设备销售价(元)，EQP_PRICE ；产品设备价(进口安全性能监检的设备价)(单位:元) EQP_SELL_PRICE设备销售价格
     * 数学误差约百万分之0.6大小。
     * JC:没有该字段; JC有"EQP_SELL_PRICE", COMMENTS: "设备销售价格", DATA_TYPE: "NUMBER"
     * */
    private Float money;

    /**【割裂考虑】监察不会把主动权让出，本平台必须被动同步外部来源的Eqp数据，那么svp区分失去依据。还是两种模式都能支持？。
     * 监察扩展，JSON非结构化存储模式的参数，能支持很多个，但是java无法简单化访问或操控单个技术参数。
     * 可加: 监察非结构化字段；前端可方便操作，后端都不参与的字段{但统计抽取方式就可除外}。
     * 未注册设备可以授权检验人员或SDN告知人员修改的，审核注册后权限关闭，相当于临时设备库倒腾。
     * 给注册时刻用的快照的申报和检验验证后的参数字段，或者监察控制修改严格的字段，只给监察用的非结构化前端字段。
     * 临时把它初始化为= USE_MOBILE；
     * 临时的尚未登记发证的可以低权限用户修改，状态改成已注册的只能高权限者做更改。
     */
    @Lob
    @Basic(fetch=LAZY)
    @Column( columnDefinition="jsonb")
    private String  svp;

    /*svp.json参数有这些：
    制造国 MAKE_COUNTRY {非行政区域实体类型关联字段}
    EQP_INST_DATE{管道单元} 跟安装单位相关；
    COMPE_ACCP_DATE 竣工验收日期 和施工单位相关； 管道才有意义；
    DESIGN_USE_YEAR 设计使用年限 DESIGN_USELIFE;  DESIGN_USE_OVERYEAR = add_months(FIRSTUSE_DATE,12*DESIGN_USE_YEAR)
    DESIGN_USE_OVERYEAR 设计使用年限到期年份?统计？使用年限到期时间;容器的设计使用年限DESIGN_USE_YEAR: "疲劳次数20000次"
    事故隐患类别：ACCI_TYPE， 类似含义字段太多了/监察操心的。ACCI_TYPE=[{id:'1':'特别重大'},{id:'2':'特大'},{id:'3':'重大'},{id:'4':'严重'},{id:'5':'一般'}];
    ACCI_TYPE {没实质性用途，}过滤统计有可能用它？；
    是否重点监控 IF_MAJCTL， 类似含义字段太多了, 含义雷同:IF_MAJEQP 是否重要特种设备。
    CONST_UNT_ID土建施工单位，仅存于监察临时表，应该是施工告知里面的。CONST_UNT_NAME 监察审核什么东西，难道给个单位名称就都放行、仅备注{没有实际意义}难道验证资质证照，验明真身是浮云。
    CONST_ACCP_UNT_ID土建验收单位, 监察临时设备表特有字段；CONST_ACCP_UNT_NAME
    JC_TEMP_EQPMGE.CONST_CLASS 施工类别 CONST_UNT_CHK_NUM施工许可证编号{很少}, CONST_START_DATE COMPE_ACCP_DATE 施工日期、验收，COMPE_ACCP_DATE竣工验收日期
    临时表才有"CONST_START_DATE", COMMENTS: "开始施工日期", DATA_TYPE: "DATE"}
    DESIGN_CHKUNT设计文件鉴定单位(才51条有数据，淘汰)，可以在告知或首检录入时低权限用户录入，然后审核登记时高权限用户触发比对关联资料，注册后更新pa.json进历史记录。
    "DESIGN_CHKUNT", COMMENTS: "设计文件鉴定单位", DATA_TYPE: "VARCHAR2"}
    DESIGNDOC_CHKDATE 设计文件鉴定日期，(才59条有有效数据，淘汰)
    DESIGN_DATE 设计日期{制造库才有意义,设备都已卖出安装了}，JC_DWXK_CASE_DEGPRO,JC_UNT_DEGPRO,JC_MAKEEQP_EQP,JC_DESIGN_PRODUCT有效期内设计产品?
    DESIGN_UNT_ID 设计单位名称/资质，管道 {设计时他有资质，注册后，失去资质呢，审核时间做资质快照的}， DESIGN_UNT_NAME管道报告用。
    JC_TEMP_EQPMGE. DESIGN_UNT_CHK_NUM 设计许可证编号   在监察临时表的锅炉容器才有的。
    PRODUCT_MEASURE 产品标准 {号}？关联标准实体列表。
    一次性验证后就不会在做修改的可关联信息{当时快照数据}：
    TYPETEST_UNT_NAME 监察单位管理 申请单,型式试验单位{高层级认定},该是针对生产单位的.属性字段?多品类批次的。TYPETEST_UNT_NAME代表产品(限制范围,典型产品)
    "TEST_UNT_ID", COMMENTS: "型式试验单位ID", DATA_TYPE: "NUMBER"}
    TEST_UNT_ID 监察,型式试验 型式试验单位; TEST_REPCOD 型式试验报告编号{历史特别检验}型式试验报告书编号，检验设备表也有。历史？关联断了线/外部来的报告=附件形式的。
    伪报告：旧系统的独立文件模式报告，外部手工报告证书，用照片上传证明的报告，甚至只有报告书编号-?关联ID/伪报告一条长久保存，分类标记=可清理删除日期。
    TEST_UNT_CHK_NUM 试验机构核准证编号
    TEST_UNT_CERT_NUM 型式试验证书编号{单位资格}  ?机构单位的属性？当前使用的证书，有效期？
    设备->型式试验Isp报告, 制造监检Isp ?
    型式试验 和 制造监检, 验收检验=3个独立！。电梯安装监督检验时，申请单位提交符合要求的电梯整机和部件产品型式试验 证书或报告。前面两个有必要保持关联方式吗/快照验证=历史数据。
    MAKE_ISP_UNT_ID制造监检机构 检验平台没有该字段 监察设备许可用的，
    MAKE_ISP_CHK_NUM监检机构核准证编号;
    MAKE_ISP_CERT_NUM 制造监检证书编号{关联制造监检 证号(批量的/人工校对包含哪些设备)、检验Isp历史}。
    这三个Isp检验机构证书:验证。 型式 制造 验收监检
    ACCEP_INSP_UNT_ID 验收检验单位(审核快照的) ACCEP_INSP_UNT_NAME ？安装监检； ACCEP_INST_REPORT_NUM 验收检验验收报告编号{查证URL}；客运索道?
    PRO_GB_UNT_ID (审核快照的)容器锅炉/产品监检单位；?首次检验==等于 验收检验？ PRO_GB_UNT_NAME 产品监检单位;
    QUACERT_COD 制造单位制造许可证号--资格证书号/监察才用； QUACERT_NAME 制造资格证书名,资格证书名称;
    DESIGN_PIC 设计图号 || 产品图号 (比较少有)；
    临时表才有的 PRODUCT_NUM 质量证明书编号=产品合格证编号;/监察才有的； 质量合格证编号
    PRODUCT_NUM 质量证明书编号,产品合格证编号{申报给监察的,如何验证/资质材料查对？网上可查证/防伪标志};
    监察才有INST_COMP_DATE 安装竣工日期 ？后端不参与字段？过滤排序分组会使用该字段吗？若不是常见需求实际可转为OLAP非实时需要ETL渠道搜索的应用场景/字段数量不同/表不同。
    EQP_SETAMOUNT 设备布置数量/ 没用? >1的才25条；

    IF_MAJCTL 是否重点监控{没实质性意义，只是显示标记的}/监察才有的,何用的,和IF_MAJEQP重复意义？
    IF_MAJPLACE 是否在重要场所{没实质性意义，只是显示标记的}/监察才有的(地址附加属性/同一个地址各类型等级设备重要性还有差异)；和 IF_MAJEQP 重复？主观、变迁。
    FIXEDASSETS 固定资产值{监察临时表中才有的}{没实质性，只是显示标记的},<售价 -减值的? +工程费附加费；
    EQP_WEIGHT 设备重 {没实质性用途，只是显示标记的}；设备总重量

    IF_POPULATED 是否人口密集区{没实质性意义，只是显示标记的}(地址附加属性？)
    IF_IN_PROV 是否省内安装，该字段已被删除。
    MANG_UNT_PHONE 管理单位电话，字段已被删除。
    ALT_CYCLE大修周期{监察才有}{没实质性，只是显示标记的}；/月、 比较较少条。
    维保 MANT_CYCLE 维保周期（检验算月数）（监察算周数）{没实质性，只是显示标记的}；比较较少条,？被荒废功能?。
    MANT_QUACERT_COD 维保单位资格证书号{监察才有}{没实质性，只是显示标记的}；比较较少条，temp表的；
    MANT_TYPE 维保型式(监察temp才有,很少条的，jc_mant_lastinfo专门表关联/仅是备案用处/统计), 维保记录实体表？流水/合同；
    jc_mant_lastinfo条数也不多?
    上次施工告知号：LAST_NOTIFY_ID,字段已被删除。 关联?
    上次事故号：LAST_ACCI_ID {没实质性意义，档案代码}[单方向关联的]关联独立事故表/历史事故记录伪表[导入生成?]。
   检验端也不可更改的技术参数(后端不会用的部分)：
    [电梯部分] 控制屏出厂编号"CONTSCRCODE"
     曳引机出厂编号"TRACANGLEAFACNUMBER"
     电动机(驱动主机)编号"ELEC_COD"
    【容器部分】 容器内径"CONINNDIA"
     */


    /**最近一次的检验记录 （在线、年度，外检）; 1系列和2系列根据设备种类监管分开。
     *尽量等到接近检验真的要开始了(或延期检验申请之前)那个流程时点，才来把isp1,isp2修改成最新的，【触发】。
     *{机电部分}电梯的、起重机械、场（厂）内专用机动车辆，大型游乐设施，客运索道：isp都是只有LAST_ISP_REPORT2一组就行;
     * 检验平台 "LAST_ISP_ID1" "最后一次检验流水号1",监察平台："LAST_ISP_COD1"
     * */
    @OneToOne(cascade = CascadeType.ALL, fetch= LAZY)
    @JoinColumn( referencedColumnName = "ID")
    private Isp  isp1;
    /**最近一次的检验记录 (机电定检，内检，全面）；  含义修正：【这个字段来自监察的数据更为合理】
     * 有可能是 正在进行的检验，甚至是正在延期当中的检验Task。
     * Task派工后，直接修改本字段isp2=new Isp();还没有开始真正检验，检验计划进行当中的？。更上一次Isp只能去历史查找了。
     * 【管道装置特殊】有多次的上一次定期报告，所以管道的Eqp同步时刻isp放空，在详细的管道单元同步时刻按规则补上。
     * */
    @OneToOne(cascade = CascadeType.ALL, fetch= LAZY)
    @JoinColumn( referencedColumnName = "ID")
    private Isp  isp2;

    //若是监检(安装、改造、大修的)出现不合格的立马监察就过不了，cping,状态就被更新，注册？？

    /**NOTELIGIBLE_FALG1 [检验给] 不合格标志1 （在线、年度，外检）:最近一次已完成的检验业务后/复检也可快照。
     为何需要这个字段？=给统计系统的快捷路数[实时核算]。业务系统没有用到啊？
     * 关联状态的快捷汇报字段，免去抽取关联，但是同步工作必须小心，否则会不一致。Isp业务驱动的；@错误依赖和不一致！
     * 还没有做出结论判定的，就直接上null；
     * 判定为不合格的*/
    private Boolean unqf1;

    /**尽量不用！    给统计系统用的;
     * NOTELIGIBLE_FALG2 [检验给] 不合格标志2 (机电定检，内检，全面）:最近一次已完成的检验业务后/复检也可快照。
     * 旧监察没有该字段;
     * 为何需要这个字段？ 快速统计的和过滤的，?： 额外需要同步Isp关联的数据。同步时机是报告完成后。
     * */
    private Boolean unqf2;

    /**LAST_ISP_CONCLU1  '最后一次检验结论1'
     * 关联状态的快捷汇报字段，免去抽取关联，但是同步工作必须小心，否则会不一致。
     * 判定不合格的，以及不合格情形下的报告结论给出的简短的关键字提示。
     * */
   // private String ccl1; 移去Isp.conclusion

    /**LAST_ISP_CONCLU2  '最后一次检验结论2'
     * 关联状态的快捷汇报字段，免去抽取关联，但是同步工作必须小心，否则会不一致。
     * 判定为合格的或者勉强合格的，带注释提示但是合格的， 还没有做出结论判定的，就直接上null；
     * */
   // private String ccl2; 移去Isp.conclusion
    /**LAST_ISP_DATE1 最后一次检验日期1【一般是外检或年度在线】
     * 并不是每种设备都需要分离成两组的，有些种类只需要 xx_ISP_xx2 一组就够。
     * 初始化新平台，本平台还没有关联数据的需要，否则实际是关联Isp数据快照，注意同步一致性。
     * */
  //  @Temporal(TemporalType.DATE)
  //  private Date ispd1; 移去Isp.ispDate
    /**LAST_ISP_DATE2 最后一次检验日期2 (机电定检，内检，全面）
     * 关联状态的快捷汇报字段，免去抽取关联，但是同步工作必须小心，否则会不一致。
     * */
  //  @Temporal(TemporalType.DATE)
  //  private Date ispd2; 移去Isp.ispDate
    //检测记录，check 检测规定时间。检测的监察也要关心？检验机构要关注检测记录的{关联检测报告历史}。
    //Instant? 纳秒时间,不使用java.util.Date
    //@Field(type = FieldType.Date, format = DateFormat.date_time)
    //规则：if等级1/3/的，耐压试验6年{2.5年}一次；

    /**NEXT_ISP_DATE1 下次检验日期1 （在线、年度）粗的检
     * 下次检验日期1+2应该归属监察平台设定范畴；本平台按照下检日期被动接任务，至少提前3个月生成Task。
     * 少部分品种的设备才需要两个系列字段都要用；  !!多数设备只需要系列2的字段;
     *【管道特殊！】 预定截止日只会找最快的吧(这个日期应该是最近的那个)，具体再分配每一个管道单元去看。
     * */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private LocalDate nxtd1;
    /**NEXT_ISP_DATE2 下次检验日期2 (机电定检，内检，全面）： 报告终结之后触发修改！监察监检也可触发。
     * 下检日期1/2: 是自动生成任务的前提，需要单独维护。
     *管道 例外，需要看具体的管道单元。
     * TO_CHAR(D.NEXT_ISP_DATE2,'YYYY')||'年'|| TO_CHAR(D.NEXT_ISP_DATE2,'mm')||'月' NEXT_ISP_DATE2,
     * TO_CHAR(D.NEXT_ISP_DATE1,'YYYY')||'年'|| TO_CHAR(D.NEXT_ISP_DATE1,'mm')||'月' NEXT_ISP_DATE1,
  【判定是否超期告警!】：下检日期！=null: 下检日期<Today.Now(), ?isp2?!=null : isp2.task?.date<.Now() && isp2.report.stm.sta==END;
     旧监察平台，NEXT_ISP_DATE2_BAK(检验平台没有该字段)，一个日期=NVL(*,*_BAK)竟然两个字段。
     * */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private LocalDate nxtd2;

    //延期检验日期1 2：ABNOR_ISP_DATE1 2 已经移入Task中。 通过isp1.task || isp2.task;

    /**下次需要检测的截至日 , 用于检测的管理,检测报告Isp+ OPE_TYPE;
     * 没有强制要求的？ nxttd!=null && nxttd<Now() 预警查询; 事情确认完成就往前滚动 nxttd=#。
     * 用户主动申请的业务，就没必要配置该字段？
     * */
    private LocalDate nxttd;

    //索引会被自动创建的。
    /**PROP_UNT_ID 产权单位, 不是监管重点 可省略null, 要看【使用单位】
     * 若null,默认=使用单位。 一般地不用产权单位来统计过滤的。 useu使用单位必须配置的。
     * 没建立索引的，不要用本字段来做搜索的过滤条件的用途，除非前面其它条件已经过滤成较少的数据个数集合。
     */
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Unit  owner;

    /**发证的监察注册机构 ID 流动设备原始发证机构 [责任起始点=注册]
     * 若null,原始发证机构就=责任监察机构；省外注册的。 注册机构 REG_UNT_ID;
     * 是否法定非注册设备 IF_NOREG_LEGAR 可推断字段='1'=注册机构=null。
     * IF_NOREG_LEGAR=1 就是 已注销的&&在用设备。 不能用ManyToOne(fetch= FetchType.LAZY)没有事务注解的就报错
     * Transactional注解必须加到graphQL接口函数，而不是内部嵌套函数上面，否则FetchType.LAZY报错no Session;那样的话只能改成FetchType.EAGER
     */
    @ManyToOne(fetch= LAZY)
    @JoinColumn(name = "regu_id")
    private Unit regu;

    /**责任监察机构 ：当前的 法定职责下的，对接监察平台的 svu不能省略。
     * REG_UNT_ID 监察注册机构ID  REG_UNT_NAME注册机构名称; REG_UNT_ID和CERT_UNT_ID可以无隶属。
     *就算设备迁出也不能是null,负责到下一个机构转入为止；
     *流动设备管理，注册监察机构和当前实际再做监察管理的机构不一样呢？历史资料／原始发证机构。
     * oid + svu 当做非标准关键字段组合2 {移装：oid 有可能修改的； oid允许为空的}。
     * 还没有oid的或者非法定设备前提条件下oid=空：就由ispu自己编制cod作为定位关键字组合。
     * 事实上关键字组合：若oid<>'' oid+svu{默认},否则ispu{默认}+cod,否则唯一性异常。
     * 没必要注解搜索啊：默认都是按地区管理啊的，从地区ad就能认定责任监察机构。？流动设备=当前设备流动地区吗？
     */
//    @IndexedEmbedded(includePaths = {"id"} )
    @PropertyBinding(binder = @PropertyBinderRef(type = NodeIdBinder.class))
    @ManyToOne(fetch= LAZY)
    @JoinColumn(name = "svu_id")
    private Unit svu;

    /**MAKE_UNT_ID 制造单位ID  监察关心！
     * makeu + model + fno 当做关键字段理论的组合1{=最牢靠唯一性判定了,因为3个字段基本不会修改}。
     *对于管道 makeu + model + fno + titl 才能确保唯一性？{管道makeu可能是空的}管道装置无制造单位;
     * 旧平台输入数据可能并没有对这些组合字段进行唯一性判定！遗留数据方式下关键字没法用！
     * 没必要注解搜索啊：有些需求实际上对应的是流处理OLAP范畴的，不适合在CRDB的后端中处理，应该在数据仓库系统批处理。
     * */
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Unit makeu;

    /**INST_UNT_ID 安装单位ID, 最早 监检   监察关心！
     * 本检验平台，感觉没必要 ES 搜索！ 若按照安装单位来做关系数据库查询？慢;
    【考虑】监察告知报检相关：本单位正在关注的待审批许可作业的设备？另外再设立多对多动态小集合关系表：或者直接转为#流程引擎@的任务驱动模式来替代关系数据库查询关联方式。
     安装，改造，甚至维修或检验核准的统统都算入一个关系集合。可建立 Set<Unit> todoApprUnits;拓展：正在报批中，已经结束，历史可删除的关系记录: 业务过程实体联系表，
     【核心】从而实现大表降为小表，来提升数据库查询性能。
     * */
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Unit insu;

    /**ALT_UNT_ID 改造单位ID; 最近做改造的，改造比维修等级资质要求高。
     * 检验平台 改造维修单位分立的。  ALT_UNT_NAME 监察平台的改造维修单位;
     * 施工告知中的  改造维修单位, 施工告知可以多条的，一次审批后，覆盖上一次的快照改造单位到svp.json中。
     * */
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Unit remu;

    /**大修： OVH_UNT_ID '维修单位' 改造要监察告知，维修等级不够格，多个层级的历史记录；
     * 多次改造维修的新单位覆盖掉旧的单位？报告中能查出历史改造单位。
     * 维保单位 MANT_UNT_ID？todo: 能合并？ 应该放在业务单告知中关联!
     * 多次维修，改造的历史业务申报单子。    ？施工告知：交给监察平台去做。
     * notify_ID 施工告知，告知单子是安装单位主动在监察平台为使用单位申请录入并提交审批的。施工告知是审批备案涉及文件和资质证明，本平台不参与了；
     # 旧平台设备台账显示的'施工单位'? 在本平台没有对应字段。
     * */
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Unit repu;

    //缺省FetchType.EAGER  不管查询对象后面具体使用的字段，EAGER都会提前获取数据。

    /**地理定位。长输管道覆盖范围大的情形特指核心地点
     * 包含了行政区域代码，楼盘定位，地理坐标。 特种设备定位位置?
     *【注意】本场景并不需要扩展地址文本串[门牌号]这么精确，不定义扩展地址文本串[门牌号]字段。
     * 而且实际上 plno{单位内部编号}字段：就等价于扩展地址文本串[门牌号]的功能用途的。
     * */
/*    @ManyToOne(fetch= FetchType.LAZY)
    @JoinColumn(name = "pos_id")
    private Address pos;*/

    /*只要哪个类出现了mappedBy，那么这个类就是关系的被维护端。里面的值指定的是关系维护端
    //缺省FetchType.LAZY  　　 .EAGER
    @ManyToMany(mappedBy="devs")
    @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL,region ="Fast")
    private Set<Task> task= new HashSet<>();
    【重大变更】 从Eqp不能直接获得task，要改成Eqp.isps.task来间接获得任务信息。 请前端注意！
     */

    /**检验检测业务记录，可长期保存历史数据。
     * 单1次ISP只能做1个EQP;考虑？一次检验很多气瓶？若支持设备汇聚出场编号汇集重新转义呢，1:N子部件设备关联表。
    //Eqp.TASK.Isp  Eqp.Isp {.短路?}  复杂关联关系， 在做EntityGraph选择定义不恰当而貌似可能死循环了？
    //ISP挂接关系到EQP底下还是挂接关系到TASK底下的？不可以两者同时都挂接关联关系，那样就是多余和混淆概念或两种分歧路径，数据多了而且还产生不一致了。
    //单个ISP检验为了某个EQP和某个TASK而生成的。
    //旧平台先有派出TASK，后来才会生成ISP； 两个地方都必须维护数据的。
    //缺省FetchType.EAGER  LAZY
    */
    @OneToMany(mappedBy="dev")
    @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL,region ="Fast")
    private List<Isp> isps;

    //底下这两组实际相当于内嵌结构对象，或者说[mtU，mtud]是复合字段的。单位ID+分支部门ID配套的才能完全表达出来。
    /**维保单位  MANT_UNT_ID MANT_UNT_NAME, maintUnt,电梯才有维保的
     * 没必要注解搜索啊：有些需求实际上对应的是流处理OLAP范畴的，另外也没直接业务需求。
     * */
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Unit mtu;
    /*针对维保单位的细化　分支机构部门。
     * MANT_DEPT_ID 监察才关心的	 .MANT_UNT_ID ,MANT_DEPT_NAME	is '维保单位ID'；检验平台没有设置该数据。
     * 监察平台实际"MANT_DEPT_ID",字段含义改成了: "维保驻点ID"，那真算不上维保单位的部门或科室的概念?
     * 功能脱离出去?: 监察平台才有电梯维保驻点的认领维保合同说明？目的=预警电梯没人去维保了，功能延申领域-电梯运行投诉管理？。
     * 【结论】交给其它服务或管理平台{监察领域}的系统去做；本平台不涉及该功能，删除吧。
     * 监察平台维保单位目前有分支机构和部门两个概念，另外附加了维保驻点概念，驻点不是科室？是单独的，又有点像组织架构图的节点，分散的工作地点。
     */
   // @ManyToOne(fetch= FetchType.LAZY)
   // @JoinColumn
   // private Division mtud;     //.MANT_DEPT_ID 监察才关心的	；检验平台实际上没有配置该数据。


    /**使用单位  USE_UNT_ID 　正常业务上单位都是用它；
     * 若是个人就一定没分支部门；[useu，usud]复合字段的；
     * 对many-to-one和many-to-many不设置级联Cascade，这要看业务逻辑的需要;对one-to-one和one-to-many设置级联。
     * many-to-many关联关系中，一端设置inverse=”false”，另一端设置为inverse=”true”。
     * 在one-to-many关联关系中，设置inverse=”true”,由多端来维护关系表；
     * */
    //@IndexedEmbedded(includePaths = {"id","company.name","person.name"} )
//    @AssociationInverseSide(
//            inversePath = @ObjectPath( @PropertyValue( propertyName = "useEqps" ) )
//    )
    @PropertyBinding(binder = @PropertyBinderRef(type = UnitNameBinder.class))
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Unit useu;     //USE_UNT_ID 使用单位ID
    /**针对使用单位的细化　管理分支部门。
     * 旧平台遗留，报告和监管机构需要细分 单位底下的 小地方分公司吗。
     *假如设备表没有指定Division部门的，那就是Unit作为缺省部门:等价于该单位底下没有细分的部门，若要求具体Division但是该单位没有细分Division情形。
     *MGE_DEPT_TYPE若=2：TB_UNT_SECUDEPT关联;   MGE_DEPT_TYPE若=1很少作废了TB_UNT_DEPT关联
     * 维保部门：要以检验为准。若检验没有数据的情形：首先找到使用单位,根据useu当前MGE_DEPT_TYPE判定 1,2? {前置条件 useu已经做了mtp设置}
     * 分支机构SECUDEPT_ID 可以采用监察，但是安全管理部门SAFE_DEPT id就要忽视掉。
     * 使用单位管理部门类型为什么对于不同设备出现多种的配置？这个设备那个品种设备会有不同的管理部门类型：【无内设，内设部门，内设分支机构】?
     * 转换和映射处理！
     * 无内设: usud=null；虽然useu也可以有部门数据。
     * 内设部门：usud 必须挑选一个部门，Division.branch=false的那些部门。
     * 内设分支机构：usud须挑选一个部门，Division.branch=true的分支。
     * 旧平台实际上安全管理部门形同作废不用；
     * 使用单位的分支机构和部门的自身数据应该由外部平台为维护者，本平台只是同步复制外部数据源中的分支机构部门数据。
     * 实际用途很少吧？？    这个没@IndexedEmbedded所以ES查不到!
     */
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Division usud;     //.SECUDEPT_ID	'分支机构ID' || .SAFE_DEPT_ID '安全管理部门'


    /**扩展的技术参数，JSON非结构化存储模式的参数，能支持很多个，但是java无法简单化访问或操控单个技术参数。
     * 可加: 设备联系人，；前端可以方便操作。
     * 修改控制等级较低的参数，容易发生变化的字段。注意：检验机构人员可能是多人的/权限分割、责任归属。
     *真正在负责定期检验的人才可以修改，非当前责任人不允许修改，空闲的未做检验也不能修改，但是例外情况审批后可修改。
     */
    @Lob
    @Basic(fetch=LAZY)
    @Column( columnDefinition="jsonb")
    private String  pa;
    /*在pa.json加这些参数：
    EXTEND_USE_YEAR 延长使用年限(数字/几年); ？检验员判定的。
    INSURANCE_INS_NAME 保险单位 监察 起重机洗才有保险机构, INSURANCE_AMOUNT 保险金额
	INSURANCE_TYPE 保险险种 INSURANCE_VALUE 保险价值 INSURANCE_PREMIUM 保险费；
    IF_WYL是否微压炉？ 检验才有的，该字段已经删除了吗!
    EMERGENCY_TEL 应急救援电话/电梯才有?/值班电话，监察维保管理的才用：
    EMERGENCY_USER_NAME 应急救援人名/？没啥用/在报告内的, 一个单位、楼盘可以不同的多个救援人。SDN申报给经过检验报告可确认修改;

    检验信息快照：todo:独立关联 年度Isp1,全面Isp2{上一次log/report}; 但是下次预定日期1,2单独的。
    非关联Isp？ LAST_ISPOPE_WENTI2 主要问题2{监察Eqp临时表的}{注册时期才有}, LAST_ISP_WENTI1 报告指出的问题1{不合格明细}监察Eqp临时表的。
    LAST_ISPOPE_TYPE2 检验类型代码2{业务名} 检验类别，最后一次检验报告类型2;
    LAST_ISP_REPORT2 报告书编号; LAST_ISP_REPORT1 上次检验报告号1 ； 非关联！来自外部平台检验？链接,仅文本编号、无法查证的。
    xx1=上次年度检验 xx2=上次全面检验； 平台割据，外部或者遗留平台的链接，非关联模式，新增伪记录Isp代替。

    REG_ISP_MONEY定检标准收费(定检、内部、全面)(单位：元);预计定检收费, ？给SDN提示的，预估可能收入？
    ACP_ISP_MONEY验收标准收费(外部、在线、年度)(单位：元); 验收标准收费(外部、在线、年度) OPE_TYPE=8,定检标准收费(定检、内部、全面) OPE_TYPE=3;
    SECURITY_LEV 和 SAFE_LEV合并字段: 安全状况等级 容器；安全状况等级(检验)
    容器；安全状况等级: 独立pa参数{报告下结论?}。
      SAFE_LEV 安全评定等级, 是设备自身的状况体现{不含外部因素}主要是检验结论评级, 动态的；
      事故隐患类别 ACCI_TYPE, 实际含义差不多，目前只有2000容器类才有{原始记录读显示}； 1级--5级数量的；
      安全评定等级 int=1,2,3,4,5 能做范围查询 4最不保险；前端映射 3级
      SAFE_LEV=[{id:'1',text:'1级'},{id:'2',text:'2级'},{id:'3',text:'3级'},{id:'4',text:'4级'},{id:'5',text:'5级'}];
    MAJEQP_TYPE 重点关注设备类型? 已删除字段！
    IF_QR_CODE 二维码
    上次检验日期1？ 上次检验日期2：？ Isp->Task任务日::还是独立日期设置最近一次的Isp1xx/2xx。上次检验业务类型：来划分1或2的。
    维保电话: 监察平台才有电梯维保驻点的认领维保合同说明？预警电梯没人去维保了。 检验平台并没实际配置维保部门；
    "WX_SIGNATURE","电梯使用标准二维码=校验码hash"=实际就是加密电梯OIDNO,最后给了编制报告;
     */


    /**监察平台给定的当前分配给哪个法定检验机构干活！ ISPUNT_NAME ISPUNT_ID (市场化标定模式,缺省的业务)
     * 缺省由svu监察主动分配的。身份匹配不对的不允许做检验？
     * 另外独立表关联映射关系，第二层级分配： 具体该单位企业下面哪个部门。第三层次分配：详细的科室。
     * 检验机构内的分配，同一设备的安装监检和定检等业务很可能归属对口多个部门的。
     * 法定检验机构可能是分配的； 责任监察机构 svu 有权分配：
     * 检测机构市场化就不是分配的。 检测业务是竞争性的。 目录外监察不管的设备是市场化ispu可修改。
     * 有80家，集中前18家。
     * cod + ispu 当做非标准关键字段组合3｛非标准是因为cod字段不是必须的可以为空的,除了空cod,其余cod+ispu组合有唯一性｝。
     * 正常应当用oid+svu是定位关键字组合; 还没有oid的或者非法定设备前提条件下oid=空：就由ispu自己编制cod作为定位关键字组合。
     * 福建特检{监察旧的分院部门归集名下：旧监察数据是单独的某某分院的}， 厦门特检， 还有很多其他机构早就分吃。
     * 【监察给的】"福建省特种设备检验研究院漳州分院"，而不是"福建省特种设备检验研究院", 注意ispu和ispud关系不是单位下属部门，需要映射转义特别处理。
    */
//    @IndexedEmbedded(includePaths = {"id"} )
    @PropertyBinding(binder = @PropertyBinderRef(type = NodeIdBinder.class))
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Unit ispu;
    /**当前法定业务检验机构内部的：本平台管控下的默认设定的归口特检院的下属检验部门。ispu->ispud关系可能不成立！#当前管理数据ispud.unit!=ispu;
     *旧监察ispu=某分院和检验平台的部门的映射关系？同步时刻转换：对应某检验部机构某部门 EQP_ISP_DEPT
     * 【遗留问题】ispu是监察平台给定的，和ispud.unit可能不是同一个单位！可允许监察平台把ispu转义模式认定为特检院的某一个分院这种管理方式。
     * 比如设备的ispu="福建省特种设备检验研究院漳州分院"&&ispud.unit="福建省特种设备检验研究院" 这种情形产生，ispud属于本平台管控设置的，ispu属于监察设置的。
     * 本平台业务主要依照ispud.unit来认定单位归属。上面的ispu字段保留用于对接监察平台系统，除非有的第三方监察平台认同这个处理方案：ispu->ispud配置数据。
     * 下面@IndexedEmbedded没标出具体字段的：直接看Division实体定义中的Hibernate Search注解声明。
     * */
//    @IndexedEmbedded
    @PropertyBinding(binder = @PropertyBinderRef(type = NodeIdBinder.class))
    @ManyToOne(fetch= LAZY)
    @JoinColumn
    private Division ispud;

    //不分哪个检测机构？可同时进行检测的；

    //检验部门应该是Task.底下的字段：前端或后端配合决定建议给某个部门做的业务，根据Adrress行政区划?+技术参数+设备级别...每个检验机构不一样规则。
    //？:【检验部门】(Task.dep?)Eqp实体没有独立的字段？应该归属哪一个部门的业务?/地区划分?业务类别不一样有可能也不同,?动态优先选择概念。


    /**事故隐患类别 ACCI_TYPE [合并字段,数据很少的！] SAFE_LEV
     * SAFE_LEV 安全评定等级 int=1,2,3,4,5 能做范围查询 5最不保险；检验员上报等级后确认，监察人员根本照顾不过来，监察只是读取。
     * 事故隐患类别ACCI_TYPE{没实质性用途，}是设备给周围带来的危险程度的评级，主要体现静态的判定。
     * 事故隐患类别 int=1,2,3,4,5{分制，递增数值} 能做范围查询 5最严重的，1最安全的，null缺省=没要求填,前端可以映射中文{0对前端等同null}。
     * 注意旧平台是 ACCI_TYPE=[{id:'1',text:'特别重大'},{id:'2',text:'特大'},{id:'3',text:'重大'},{id:'4',text:'严重'},{id:'5',text:'一般'}];
     * 旧平台ACCI_TYPE有数据的很少=才373条， 没啥用的字段，干脆合并进来SAFE_LEV 对于容器基本都用到的。
     * 容器技术参数；安全状况等级SECURITY_LEV很多数据:取值范围和SAFE_LEV一致； 容器的技术参数安全状况等级予以保留。
     * SAFE_LEV 安全评定等级  字段合并后就删除。 ；SAFE_LEVEL是管道单元的特有字段 安全状况等级：SAFE_LEVEL。
     * 结论：容器技术参数；安全状况等级SECURITY_LEV 接替SAFE_LEV 安全评定等级，其它种类的设备的安全评定等级=SAFE_LEV 融合进了 事故隐患类别 中。
     * ACCI_TYPE+? ['一般','严重','重大','特大','特别重大']; 接口和DB直接用1,2,3,4,5整数序号存储。
     * SAFE_LEV? 反过来;
     */
    private Byte cpa;

    /**注册登记日期 REG_DATE ;关联 regu
     * */
    private LocalDate regd;

    /**注册登记注销日期 REG_LOGOUT_DATE
     * 谁有权利注销 注册机构regu 自己：
     * */
    private LocalDate cand;

    /**注册登记人员REG_USER_NAME 注册人员姓名  监察JC: REG_USER_ID注册人员{关联操作日志}
     * 状态变更; 注册 流水日志，注销记录？到底谁敢干的；旧平台导入数据的：历史用户以往旧人员呢？
     * 注册历史记录，关联操作User实体的, 可历史记录太旧的可能被当做垃圾数据删除。
     *该字段若是类型改为User？改Person实体关联来做，Person还会死亡注销也成垃圾数据。可改成中文姓名String(同名的)，爱查就去找Log,姓名修改
     * JY:没有字段REG_USER_ID。
     */
    private String  rnam;

    /**注销人员, 中文姓名 关联操作记录
     * 使用状态报停的经手人员，操作记录；特别旧平台导入新平台如何处理？旧平台关键历史记录也得导入或伪增。
     * 前端都没有显示：注册状态的注销人；
     * */
    private String  cnam;

    /**发短信用 设备联系人手机号，USE_MOBILE 设备联系手机
     *直接关联Person实体类可能信息更新速度不够快/检验员直接修改最及时，检验员对真假负责。
     * */
    private String lpho;

    /**进口类型,IMPORT_TYPE计费依据 IMPORT_TYPE 进口类型
     *额外收费要求定义的字段！ "国产";"整机进口起重机械，加收20%" "整机进口大型游乐设施，加收50%"
     * "国产""整机进口""部件进口""非进口" ，就这几个可能取值的。 [{id:'国产',text:'国产'},{id:'部件进口',text:'部件进口'},{id:'整机进口',text:'整机进口'}];
     * 硬编码Enum模式： null,旧平台编码 0='国产', 1='部件进口' ,2='整机进口'
     * 前端0值无法选择Select所以，必须转换下编码：1='国产', 2='部件进口' ,3='整机进口'
     * 实际数据应当 !=null, !=''
     * */
    private Byte impt;

    /**上路号牌： 厂车牌照 CATLICENNUM  汽车罐车也有？
     * 罐车牌号"CARSIGN"  VEHIC_NUM   明显给人看的设备身份号码：从观众角度辨识。类比监察识别码；
     * */
    @KeywordField
    private String  plat;

    //正常这个字段不能为空的！
    /**使用地，非等于注册地【前缀，行政地理描述部分】     用于提高搜索判定速度。
     * 管道跨越地域特大的设备地址：??能否开口子 Adminunit设置成区县市级的，不用最小镇级别的。管道的监察机构就能指引行政区域。
     * ES扁平化处理的需求解决思路： Adminunit{5级行政字段全部拆开独立列出： 过滤字段场景}；全地址描述字符串搜索场景可以直接组合生成在MySQL中没有的字段。
     * ES 5级行政字段+ 最小行政区内部地址(短地址=name) +全地址字符串{给ES搜索配套的,合成的地址}:full=Adminunit.prefix+name;?不包含扩展地址文本串[门牌号];
     ad字段对应Adminunit实际数据不一定非要最小的行政区划！外国的区划太细到了街道乡镇也没啥意义。国外行政区划配置简单点；具体地址可以挪到扩展字段extAdr附加表达清楚。
     【同步思路】来源附带有地区码有效Adminunit，就按地区底下去根据原始地址为关键字查找已经存在的Address；没有效Adminunit的只能原始地址为关键字全表查找。
     但是若有和目前经纬度GEO相差较大的就应该认定为不同的Address；
     旧平台地区码很多不是定位到最小行政级别的！
     Eqp同步如果已经有了Village那么需要根据楼盘的地区和楼盘地址的前提下查找定位。楼盘地址:+:A1地块2#楼；追溯同步更新？
     楼盘Adminunit和这里的ad不一致情况？ad改成成楼盘地区码：附带有效Village的，以楼盘+原始地址为关键字查找;{ad+name}可能抛唯一性异常！
     * */
//    @IndexedEmbedded
    @PropertyBinding(binder = @PropertyBinderRef(type = AdminunitBinder.class))
    @ManyToOne(fetch= LAZY)
    @JoinColumn(name = "aid")     //去掉nullable=false，会导致初始化表缺省aid=0
    private Adminunit ad;       //行政区划; 有些同步来源就没指出地区代码。同步生成的需要后期人工合并地址！。

    /**【地址描述文本串部分】扣除掉行政区划对应的地址前缀，用户地址命名空间 部分。  楼盘不属于地址组成部分/楼盘属于名义地址。
     * 旧系统地址部分很多是 针对使用单位来讲的 简易描述。
     * 竟然有管道，它的监察机构是莆田局的，安装区域也是莆田，可是实际使用地址却在厦门的情况? 特殊的内部转义地址,报告编制显示允许修改实际地址。
     * ES简易包含全文的地址叙述的；Elasticsearch目前没考虑把ad的前缀地址部分直接加入到address；
     * 遗留旧平台给的数据也是？是全地址为首规范的。address还是考虑浪费一点数据库存储，ad作为辅助性质，address作为建议地址，发快递时可手动编辑地址可独立修改邮递发件地址。
     * 策略：保留部分重叠叙述？
     * 配合Adminunit把ES上相应本字段改造为包含了区域名的全文本地址，国内应用：中国两个字前缀省略掉。
     * */
    @FullTextField
    private String  address;     //前面行政地理描述部分要省略掉。

    /**楼盘 住宅小区 厂区;  Village是附带性质标签!，可以null;也不影响地址描述文本串。
     * 并非是强制都要求的地址管理部分，可以空缺。    电梯 才需楼盘名与维保
     *楼盘小区 大厦名字，可另外并行独立出去。              String building;
     *广义模糊地址；
     *楼盘=地址的泛房型表达式;     单独设立一个模型对象。　(楼盘名称)＝使用地点！=使用单位的单位地址。
     *private Long  buildId;    //暂用 BUILD_ID  楼盘ID
     *两个字段 ad 和 vlg.Adminunit应该保持相容。
     *IndexedEmbedded没明确限定的：其具体ES索引的定义进入 Village 模型类找ES相关定义@FullTextField之类的;
     * 若(fetch= EAGER)会合并到主查的语句中去，否则独立语句。
     * */
//    @IndexedEmbedded
    @PropertyBinding(binder = @PropertyBinderRef(type = NodeIdNameBinder.class))
    @ManyToOne(fetch= LAZY)
    @JoinColumn(name = "vid")
    private Village vlg;

    //地址需要再次丰富掉， 省 市 区 镇 小区。
    //【特别注意】EQP_AREA_COD 检验比监察定位更细的；
    // private String  area;   //地区码 "zipCode": "",          area;   //地区码
    //UnitAddress 广域 1 : N Position 门牌栋号　+。
    //经纬度坐标小数位与精度的对应关系 https://www.jianshu.com/p/cff30c491a0b
    /**经纬度， 用于搜索的意义多大？  假如要的就参考注解@GeoPointBinding(fieldName="")
     * 监察平台可能用来收缩范围， 而检验平台没这需求。
     * */
    private Double lat;  //纬度 ;精确到小数点后6位可达约1米精度。 ？综合考虑地址所有关联多个设备原始数据，同步时期还未人工确认以最新数据为准。
    private Double lon;  //经度  前面的是纬度,后面的是经度； 其它同步来源不一定有Geo: tb_unt_mge  jc_unt_mge有。
    //Point ( x=lat  ,y=lon ); "lat": 48.86111099738628, "lon": 2.3269999679178
    //private Point pt;  //直接java序列化占用mysql磁盘很大，pt=79个字节。 org.springframework.data.geo.Point;
    //地理定位。  .EQP_LONG is '地理经度'     .EQP_LAT is '地理纬度'


    /**所在位置：公众聚集场所？: 预定义标签： JC_DICT_COMMON 检验监察一致；
     * 设备使用场所--字典库； EQP_USE_PLACE；  只有4000起重机械才会使用登记证上注明本字段的{混淆！}; JC_TASK_EQP,报告会用到。
     EQP_USE_OCCA 使用场合，@ EQP_USE_OCCA起重机械才用;
     旧检验监察平台EQP_USE_PLACE=Long{实际也不是对象ID，而是内部序号。}看似关联ID！"设备使用场所--字典库"旧平台大表==聚合形式的对象库？
     EQP_USE_PLACE=[{id:'1',text:'公众聚集场所（学校）'},{id:'2',text:'公众聚集场所（幼儿园）'},{id:'3',text:'公众聚集场所（医院）'},
     {id:'4',text:'公众聚集场所（车站）'},{id:'5',text:'公众聚集场所（客运码头）'},{id:'6',text:'公众聚集场所（商场）'},{id:'7',text:'公众聚集场所（体育场馆）'},
     {id:'8',text:'公众聚集场所（展览馆）'},{id:'9',text:'公众聚集场所（公园）'},{id:'10',text:'公众聚集场所（其它）' '其它公众聚集场所' },
     {id:'11',text:'住宅'}];
     IF_PUBLIC_AREA 是否公共领域（0不是，1是），JC没有啊:已被删除字段?
     IF_MAJPLACE 是否在重要场所{没实质性意义，只是显示标记的},
     IF_POPULATED 是否人口密集区{没实质性意义，只是显示标记的}
     数据组织形式 ??Enum； Object+Id； String[]？  string"1,2.";
     【简单地】贴个标签=针对特种设备关注的：=设备使用场所
     实际上做了标记的也不多啊：'住宅'6675条，{'住宅'实际没意义？}'公众聚集场所（其它）'1422条，其他的1500条；
     ！# Elasticsearch反而可简单定义多值 String[] plcls; 反而是JPA数据库这里卡住,不好弄[]数组。
     * */
    private String  plcls;

    /**是否处于人口密集区的位置 IF_POPULATED(地址附加属性？), 才53条；？==》eqp.svp. 检验String 监察int
     * */
    private Boolean  dense;

    /**是否标记为重要场所的位置 IF_MAJPLACE, 是否在重要场所{没实质性意义，只是显示标记的}, 才1443条；
     *针对特种设备管理而言的：
     * */
    private Boolean  seimp;
    /**对于可能被非结构化json关联本对象的模型@ ，必须保证本对象生存期超过1天时间，免于同一天内的相同id出现。
     * 删除对象【注意】确保crDate不是今天也即1天以上的才能Delete掉。
     * 为了非结构化json关联本对象而设置的；杜绝重复id碰撞，针对生存期超过一天的对象的。
     * */
    //https://blog.csdn.net/weixin_45815061/article/details/128112339
//    @CreatedDate  必须要配合上层注解才能生效？？  还是算了：直接程序负责管理了@Builder.Default
    @Builder.Default
    @Column(updatable = false)
    private LocalDate  crDate= LocalDate.now();

    //@PropertyDef(label="别码") 数据库建表注释文字。 https://github.com/dwhgygzt/jpacomment-spring-boot-starter
    /**同步数据环节的处理结果*/
    private String fail;
    //@Transient用法，非实际存在的实体属性，动态生成的实体临时属性字段。
    //大规模数据集查询不可用它，效率太慢，应该。。
    //本函数执行之前，JPA数据实际已都取完成了。
    //安全考虑，过滤isps字段合理输出,代替原来缺省的getXXX
    //@org.springframework.data.annotation.Transient  俩个注解都一样
   // @Transient

    public Connection<Isp> isps(DataFetchingEnvironment env) {
        //需排序??
        return new MemoryListConnection(isps.stream().collect(Collectors.toList())).get(env);
    }

    /**因为这个EqpController特殊，无法使用implements IdMapper<Eqp>， 只能手动加：
     也没法走 @SchemaMapping(typeName="Equipment", field="id" ) 这个路子的。
     幸好这个方法可行：
     前端太严格报错expected both versions of record  to have the same `__typename` but got conflicting types `Eqp` and `Elevator`
     *  */
    public String getId(DataFetchingEnvironment env) {
        //用"Eqp"会在详情页和报告列表页冲突。用固定一个"Equipment"照样s报错  不同前端接口内省的：type不一样？ 普通接口都是`Eqp`，特别接口才会知晓是`Elevator`
        //其它模型可以用 String typeName2=this.getClass().getSimpleName();
        String typeName= null!=env? ((GraphQLObjectType)env.getParentType()).getName() : this.getClass().getSimpleName();
        return Tool.toGlobalId(typeName, this.id);
    }

}




//EntityGraph用处：用来避免Lazy延迟加载导致的代码失败问题，内部附带效果：减少了发给数据库的select语句条数。
//定义多个 @NamedAttributeNodes 以定义更复杂的图，也可以用 @NamedSubGraph 注解来创建多层次的图。https://thoughts-on-java.org/jpa-21-entity-graph-part-2-define/?utm_source=rebellabs
//lazy/eager loading at runtime延迟加载变成可以动态参数Map hints指定了fetchgraph;  　 @NamedSubgraph指定多层的。
//EntityGraph的定义范围：实际针对的是从上往下看单向LAZY的关联对象字段，EntityGraph才是有用的。
//非 web 请求下的懒加载问题解决  https://blog.csdn.net/johnf_nash/article/details/80658626
//JPA 一对多延迟加载与关系维护,属性级延迟加载blob大字段   https://blog.csdn.net/lhd85/article/details/51692546
//访问延迟属性若EntityManager这个对象被关闭，我们再去访问延迟属性的话，就访问不到，并抛出延迟加载意外;spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
//枚举，enum转换器 @Converter(autoApply = true)  ； https://thoughts-on-java.org/jpa-21-type-converter-better-way-to/

/* 删除没用的头注解： 用@EntityGraph(value="Eqp.task",)做查询优化可不容易掌控的；很容易出笛卡儿积爆炸问题。
@NamedEntityGraphs({
        @NamedEntityGraph(name= "Eqp.task",
                attributeNodes = {
                        @NamedAttributeNode(value= "task",subgraph= "taskg"),
                },
                subgraphs = {       嵌套的指示，下一级关联对象的hits;
                        @NamedSubgraph(name = "taskg", attributeNodes =
                                { @NamedAttributeNode("isps"),  }
                        ),
                }
        ) ,
        @NamedEntityGraph(name = "Eqp.isps",
                attributeNodes = {
                        @NamedAttributeNode(value= "isps",subgraph= "ispsg"),
                }
        )
})
*/

//无法引用其他schema底下的表的外键？建立同义词(synonym)＋授权。
//@Table( schema="newsei")    Oracle下就等于用户，似乎没啥必要性，管理更麻烦。Oracle下RAC数据库可被多实例所使用。

/*
@NamedEntityGraphs({  每个NamedEntityGraph都是独立无关的hints，若一个查询语句同时加上多个hint，底层它该如何协调;底层API不会精确区分把控上层应用实体的真正目的。
        @NamedEntityGraph(name = "Eqp.all",    某个场景用一个hint;
                attributeNodes = {}  )      //实际上attributeNodes可以多个，但是特别小心，关联不密切的关联对象一次性join=会产生爆炸记录数！！attributeNodes只做一个较妥。
        @NamedEntityGraph(name = "Eqp.special",    另外一个场景用另外一个hint;
                attributeNodes = {}  )
    })
join爆炸记录数范例 @NamedEntityGraph( name="Eqp.task",attributeNodes={　@NamedAttributeNode("task"),　@NamedAttributeNode("isps")　} )  无关的task+isps搞在一起＝爆炸。
JPA日期字段短的需要加@Temporal(TemporalType.DATE)节省硬盘，否则缺省是=@Temporal(TemporalType.TIMESTAMP)长的。
*/

//注解定制索引，没啥实际意义。
//@Table(indexes={ @Index(name="type_idx",columnList="type"),
//         　 @Index(name="factoryNo_idx",columnList="fNo")  } )

//二级缓存可移植性@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Fast") 这里region是按照配置来区分的区分标识，竟然不省略。

/*树形层次分类设备； https://baike.baidu.com/item/%E7%89%B9%E7%A7%8D%E8%AE%BE%E5%A4%87%E7%9B%AE%E5%BD%95/19834714?fr=aladdin#2
vart是复合字段就可以唯一表示出设备类型(国家标准范围),vart的3个字符按照顺序分别拆解出type,sort类型。subv是独立的扩展{针对sort}。
type,sort,vart,subv设备细分类别，实际前端采用的多，算展示层映射用的。后端服务器主要用于计费/报告类型的控制。
subv是国家标准之外扩展的分类标记，实际附带于sort底下的，目的用于修饰vart的细分类型。
type,sort,vart三个是层次化的以3个单个字符来组合的属性=复合字段分解为3个字段。
type有：
3 电梯
 sort有：
 31 曳引与强制驱动电梯
    vart有：
    311 曳引驱动乘客电梯
    312 曳引驱动载货电梯
    313 强制驱动载货电梯
    subv在31底下的有：
    3001 有机房电梯
    3002 无机房电梯
 32 液压驱动电梯
    vart有：
    321 液压乘客电梯
    322 液压载货电梯
    subv在32底下的=无： {32底下目前没有3002该细分型}3210有16条3001细分？问题数据
 33 自动扶梯与自动人行道
    vart有：
    331 自动扶梯
    332 自动人行道
    subv在32底下的=无： 已有的是问题数据
 34 其它类型电梯
    vart有：
    341 防爆电梯
    342 消防员电梯
    343 杂物电梯
    subv在34底下的有：
    3001 有机房电梯
    3002 无机房电梯
 <3, 3000,3000,9999无细分>?是问题数据: 待注册+未投入使用的?还未决定细分和具体种类，字段可为空=未决定。
2 压力容器
    sort有：
    21 固定式压力容器
        vart有：
        211 超高压容器
        213 第三类压力容器
        215 第二类压力容器
        217 第一类压力容器<低压>
        subv在21底下的有：
        2001 大型压力容器
        2002 球形容器
        2003 液化气体储配站
        2004 非大型压力容器
        2005 超高压容器
        2006 超高压水晶釜
    22 移动式压力容器
        221 铁路罐车
        222 汽车罐车
        223 长管拖车
        224 罐式集装箱
        225 管束式集装箱
        subv在22底下的=无：
    23 气瓶   {监察上独立出去,钢瓶数量庞大单个设备目标当量很低,每个瓶子一份报告?打印个标签还差不多,登记在案}
        231 无缝气瓶
        232 焊接气瓶
        23T  特种气瓶（内装填料气瓶、纤维缠绕气瓶、低温绝热气瓶）
        subv在=无：
    24 氧舱
        241 医用氧舱
        242 高气压舱
        subv在=无：
4 起重机械
    41: "桥式起重机"
        411: "通用桥式起重机",
        413: "防爆桥式起重机",
        414: "绝缘桥式起重机",
        415: "冶金桥式起重机",
        417: "电动单梁起重机",
        419: "电动葫芦桥式起重机",
        subv在=无：
    42: "门式起重机"
        421: "通用门式起重机"
        422: "防爆门式起重机"
        423: "轨道式集装箱门式起重机"
        424: "轮胎式集装箱门式起重机"
        425: "岸边集装箱起重机"
        426: "造船门式起重机"
        427: "电动葫芦门式起重机"
        428: "装卸桥"
        429: "架桥机"
        subv在42=无：
    43: "塔式起重机"
        431 普通塔式起重机
        432 电站塔式起重机
        subv在=无：
    44: "流动式起重机"
        441 轮胎起重机
        442 履带起重机
        444 集装箱正面吊运起重机
        445 铁路起重机
        4490 4480 4430 =飞出目录
        subv在=无：
    47: "门座式起重机"
        471 门座起重机
        476 固定式起重机
        subv在=无：
    48: "升降机"
        486 施工升降机
        487 简易升降机
        vart='4890'例外1条； 488,489=飞出目录了
        subv在底下的有：
        4871 简易升降机（电动葫芦式）
        4872 简易升降机（曳引式）
    49: "缆索式起重机"
        491 缆索式起重机{490也成}
        subv在=无：
    4A: "桅杆式起重机"
        4A1 桅杆式起重机
        subv在=无：
    4D: "机械式停车设备"
        4D1 机械式停车设备{4D0也成} ='4D0'有几台：差错？
        subv在4D底下的有：
            "4001": "升降横移类机械式停车设备",
            "4002": "垂直循环类机械式停车设备",
            "4003": "多层循环类机械式停车设备",
            "4004": "平面移动类机械式停车设备",
            "4005": "巷道堆垛类机械式停车设备",
            "4006": "水平循环类机械式停车设备",
            "4007": "垂直升降类机械式停车设备",
            "4008": "简易升降类机械式停车设备"
    sort=4C00||4B00{已经飞出特种设备目录表了}的数据没啥用。
8 压力管道
    "81": "长输管道",
        811 "输油管道"
        812 "输气管道"
    "82": "公用管道",
        821 "燃气管道"
        822 "热力管道"
    "83": "工业管道",
        "831": "工艺管道",
        "832": "动力管道",
        "833": "制冷管道",
1 锅炉
    "11": "承压蒸汽锅炉",
        111 "承压蒸汽锅炉"
        subv在11底下的有：
        "1002": "电站锅炉",
        "1003": "工业锅炉",
    "12": "承压热水锅炉",
        121 "承压热水锅炉"
        subv在12底下的有：
        "1002": "电站锅炉",
        "1003": "工业锅炉",
    "13": "有机热载体锅炉",
        "131": "有机热载体气相炉",
        "132": "有机热载体液相炉",
        subv在13底下的有：
        "1002": "电站锅炉",
        "1003": "工业锅炉",
     ?遗留数据"1001"  ‘’  ‘9999’ subv也有不少的记录！
5 场（厂）内专用机动车辆
    "51": "机动工业车辆",
        511 "叉车"
        非标准目录的：5120 "叉车(防爆功能)" 有24条数据?, 涉及报告？收费？
    "52": "非公路用旅游观光车辆",
        521 "非公路用旅游观光车辆"
        而 5220 5230 =飞出目录
        subv在52底下的有：
        "5001": "内燃类",
        "5002": "电动类",
     "5C00" "5B00"= 飞出目录
6 大型游乐设施
    "61": "观览车类",
        611 "观览车类"
    "62": "滑行车类",
        621 "滑行车类"
    "63": "架空游览车类",
        631 "架空游览车类"
    "64": "陀螺类",
        641 "陀螺类"
    "65": "飞行塔类",
        651 "飞行塔类"
    "66": "转马类",
        661 "转马类"
    "67": "自控飞机类",
        671 "自控飞机类"
    "68": "赛车类",
        681 "赛车类"
    "69": "小火车类",
        691 "小火车类"
    "6A": "碰碰车类",
        6A1 "碰碰车类"
    "6B": "滑道类",
        6B1 "滑道类"
    "6D": "水上游乐设施",
        "6D1": "峡谷漂流系列",
        "6D2": "水滑梯系列",
        "6D4": "碰碰船系列",
        "6D30" "6D60" = 飞出目录
    "6E": "无动力游乐设施",
        "6E1": "蹦极系列",
        "6E4": "滑索系列",
        "6E5": "空中飞人系列",
        "6E6": "系留式观光气球系列"
        subv在6E底下的有：
        "6001": "高空蹦极系列",
        "6002": "弹射蹦极系列",
        "6003": "小蹦极系列",
        ?"6004": "滑索系列", ?  和"6E4"重合，数据问题？报告/计费？
        subv?"6005" ?"6006": 没数据；
9 客运索道
    "91": "客运架空索道",
        "912": "循环式客运架空索道",
        "911": "往复式客运架空索道",
    "92": "客运缆车",
        "922": "循环式客运缆车",
        "921": "往复式客运缆车",
    "93": "客运拖牵索道",
        "932": "高位客运拖牵索道",
        "931": "低位客运拖牵索道",
R 常压容器 <非国家标准目录的>  ocat=true 是目录外
    "R3":"危险化学品常压容器"
        "R31": "液体危险货物常压容器(罐体)",
        "R32": "危险化学品常压容器",
F 安全附件 <标准目录的> 。
    731 安全阀?? 不能独立构成一个设备,算附加的也需要定期校验，监管目标太小了，检验管理太细了，无法进入Eqp设备模型的表。但是有单独报告/收费。
7 压力管道元件 {目录内，给制造生产的}
    制造的，一次性的，批次的雷同多个单元；没必要进入Eqp设备表。
    "71": "压力管道管子",
    "72": "压力管道管件",
    "73": "压力管道阀门",
    "74": "压力管道法兰",
    "75": "补偿器",
    "77": "压力管道密封元件",
    "7T": "压力管道特种元件",
R000,Z000水质,F000安全阀=仅存在于任务流程
【新设备】入口：
1， 检验-检验机构首检录入,录入{=新设备推送给监察(临时表等待?正式表)};  #监察不关心的设备=目录外的设备#
2， 监察-施工告知录入,施工告知，录入; =*管得最严格模式*  #监察施工告知操作的同时应该率先在本平台新增基础数据,省略掉旧的监察临时表大部分字段# 施工种类细节？
    施工单位信息：许可证编号关联选择的，有效期。 设备清单【多台】 附件+证书。 告知单编号：受理结果｛受理编号 收悉,要监检(首检)｝；施工告知仅仅是启动步骤。
        ？类似菜单“无损检测告知代入”，（单子数量很少）不是设备？检测单位信息+证书！+附件；
3， 监察-使用登记申请代录入,只能新增压力容器、压力管道、外省流动作业起重机械，省外流动设备=新增;导入检验系统设备=导入; #应当在本平台新增基础数据,省略掉旧的监察临时表大部分字段#
   *? 可以把原来注册使用登记申请表的字段录入改道到本平台设备技术参数的输入，一部分在技术参数中，一部分在申请单附加录入。上传附件（证明材料），关联文件？使用登记申请材料补正收件清单*
      导入拟注册设备。只有在查不到设备的情况下才能新增设备：｛临时表的编辑器+主要性能参数[]+其它技术参数｝
4， 监察-首检录入, 电梯、锅炉不允许新增首检录入{？前置条件是施工告知？};  #检验机构在本平台早就有增加数据--再次引用即可#  审核(检验推送)超时自动导入;
        临时表的字段大多数在这里的编辑器【首检设备录入】体现了; 技术参数没有要录入。
*/


/* @数据库修改脚本：【根据业务需要制定】   最新IDEA工具终于可以直接including STORING()附属存储字段。
CREATE INDEX eqp_useu_id_usud_id_index ON public.eqp USING btree (useu_id ASC, usud_id ASC);
CREATE INDEX eqp_isp1_id_index ON public.eqp USING btree (isp1_id ASC);
CREATE INDEX eqp_isp2_id_index ON public.eqp USING btree (isp2_id ASC);
CREATE INDEX ON seipf.public.eqp (cod, ispu_id) STORING (dtype, address, cand, cerd, cert, cnam, cpa, cping, crdate, dense, expire, fail, fno, impt, insd, lat, level, lon, lpho, mkd, model, money, move, nxtd1, nxtd2, nxttd, ocat, oid, pa, plat, plcls, plno, rcod, reg, regd, rnam, seimp, sno, sort, subv, svp, titl, type, unqf1, unqf2, uscd, used, ust, vart, version, vital, asemb, bmod, form, fuel, power, pres, wall, fulw, highs, insul, jakm, mdi, mont, pnum, prs, rtlf, vol, weig, mtm, pow, auxh, cap, cotr, cpi, cpm, cvl, flo, grab, hlf, hlfm, jobl, lmv, luf, luff, metl, miot, mom, mvl, nnor, ns, occa, opm, part, pcs, pcw, rang, rtv, rvl, scv, span, suck, tm, tno, two, twoc, vls, walk, whole, wjib, matr, temp, angl, grad, high, leng, mbig, sdia, vl, rtl, aap, buff, doop, lbkd, lesc, limm, nbkd, oldb, prot, spec, wesc, aid, insu_id, isp1_id, isp2_id, ispud_id, makeu_id, mtu_id, owner_id, regu_id, remu_id, repu_id, svu_id, useu_id, usud_id, vid);
    后面STORING没必要。
CREATE INDEX ON seipf.public.eqp (oid, svu_id) STORING (dtype, address, cand, cerd, cert, cnam, cod, cpa, cping, crdate, dense, expire, fail, fno, impt, insd, lat, level, lon, lpho, mkd, model, money, move, nxtd1, nxtd2, nxttd, ocat, pa, plat, plcls, plno, rcod, reg, regd, rnam, seimp, sno, sort, subv, svp, titl, type, unqf1, unqf2, uscd, used, ust, vart, version, vital, asemb, bmod, form, fuel, power, pres, wall, fulw, highs, insul, jakm, mdi, mont, pnum, prs, rtlf, vol, weig, mtm, pow, auxh, cap, cotr, cpi, cpm, cvl, flo, grab, hlf, hlfm, jobl, lmv, luf, luff, metl, miot, mom, mvl, nnor, ns, occa, opm, part, pcs, pcw, rang, rtv, rvl, scv, span, suck, tm, tno, two, twoc, vls, walk, whole, wjib, matr, temp, angl, grad, high, leng, mbig, sdia, vl, rtl, aap, buff, doop, lbkd, lesc, limm, nbkd, oldb, prot, spec, wesc, aid, insu_id, isp1_id, isp2_id, ispu_id, ispud_id, makeu_id, mtu_id, owner_id, regu_id, remu_id, repu_id, useu_id, usud_id, vid);
    Unit不能删除，不然Eqp这里很多外键关联unit实体都需要添加索引的。时间久了,Unit表会遗留垃圾数据没删除，很多遗留Unit数据！考虑突击一个时间来集中清理模式更妥。
    维护初始化导入期需要cod+isp oid+svu建索引，台账进入ES以后，正常查询直接走ES了，就不需要利用该索引。但是外部监察台账同步接口？也要首先查ES引擎，ES和DB已能同步。ES reindex?
    division 和 village,adminunit也不要删除，division虽然有索引但是前面是{unit+的}:若删除division没法利用该索引。
    FOREIGN KEY(ispu_id)  FOREIGN KEY(ispud_id)外键要建索引? 过滤或外键关联删除的情况导致需加索引。ES库有搜索字段。Task任务表初始化过程也已经从EqpES倒库也没用从Eqp实体表过滤方式。
为何遗留这个？ CONSTRAINT check_reg CHECK (reg BETWEEN 0:::INT8 AND 3:::INT8),
【JPA enum问题】自动构建之后，无法修改！ #需人工做 ALTER TABLE public.eqp DROP CONSTRAINT check_reg;否则还是旧的约束！生成数据库表旧的字段无法删除修改类型也不能同步改，也需手动维护。
* */
